package org.pentaho.cubic.client.dialogs;

import java.util.Date;

import org.pentaho.cubic.client.service.CubicServiceCache;
//import org.pentaho.cubic.client.service.ICubicLoginServiceAsync;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class LoginDialog extends DialogBox {

	private static LoginDialogUiBinder uiBinder = GWT
	.create(LoginDialogUiBinder.class);

	interface LoginDialogUiBinder extends UiBinder<Widget, LoginDialog> {
	}

	//private static ICubicLoginServiceAsync SERVICE;
	private AsyncCallback<Boolean> outerCallback; // from outside context

	@UiField HTML htmlNotify;
	@UiField TextBox txtUsername;
	@UiField PasswordTextBox txtPassword;
	@UiField Button btnOK;
	@UiField Button btnCancle;

	public LoginDialog() {
		setWidget(uiBinder.createAndBindUi(this));
		this.setText("Login");
		this.setGlassEnabled(true);

		(new Timer() {
			@Override
			public void run() {
				txtUsername.setFocus(true);
			}
		}).schedule(1);

	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public LoginDialog(AsyncCallback callback) {
		this();
		setCallback(callback);
	}

	@UiHandler("btnOK")
	void onClickOK(ClickEvent e) {
		if (validate()) {
			Authenticate();
		}
	}

	@UiHandler("btnCancle")
	void onClickCancle(ClickEvent e) {
		this.hide();
	}

	@UiHandler("txtUsername")
	void onChangeValueUsername(KeyUpEvent e) {
		if (e.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
			txtPassword.setFocus(true);
		}
	}

	@UiHandler("txtPassword")
	void onChangeValuePassword(KeyUpEvent e) {
		if (e.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
			if (validate()) {
				Authenticate();
			}
		}
	}

	private void Authenticate() {
		// Prepare
		//Window.alert("1");
		String path = Window.Location.getPath();
		if (!path.endsWith("/")) { //$NON-NLS-1$
			path = path.substring(0, path.lastIndexOf("/") + 1); //$NON-NLS-1$
		}
		RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, path + "j_spring_security_check"); //$NON-NLS-1$
		builder.setHeader("Content-Type", "application/x-www-form-urlencoded"); //$NON-NLS-1$ //$NON-NLS-2$
		//Window.alert(path + "j_spring_security_check");

		// Callback
		RequestCallback callback = new RequestCallback() {

			public void onError(Request request, Throwable exception) {
				outerCallback.onFailure(exception);
				//setNotify("Error: " + exception.getMessage());
				setNotify("Authentication Failed");
				btnOK.setEnabled(true);
				return;
			}

			public void onResponseReceived(Request request, Response response) {
				final AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {

					public void onSuccess(Boolean result) {

						if (result) {
							long year = 1000 * 60 * 60 * 24 * 365;
							// one year into the future
							Date expirationDate = new Date(System.currentTimeMillis() + year);
							Cookies.setCookie("loginNewWindowChecked", "" + false, expirationDate); //$NON-NLS-1$ //$NON-NLS-2$
							setNotify("Authenticated");
							hide();
							//Window.alert(Window.Location.getPath());
							//Window.alert("OK");
							outerCallback.onSuccess(false);
						} else {
							outerCallback.onFailure(new Throwable("Authentication Failed"));
							//setNotify("Authentication Failed: Check Username or Password ");
							setNotify("Authentication Failed");
							btnOK.setEnabled(true);
							return;
						}
					}

					public void onFailure(final Throwable caught) {
						outerCallback.onFailure(caught);
						//setNotify("Authentication Failed: " + caught.getMessage());
						setNotify("Authentication Failed");
						btnOK.setEnabled(true);
						return;
					}
				};
				//Window.alert("Before Check");
				CubicServiceCache.getService().isAuthenticated(callback);
				//SERVICE.isAuthenticated(callback);
				//Window.alert("After Check");
			}
		};

		//Window.alert("3");
		// Send Request
		btnOK.setEnabled(false);
		try {
			String username = txtUsername.getText();
			String password = txtPassword.getText();
			builder.sendRequest("j_username=" + URL.encodeComponent(username) + "&j_password=" + URL.encodeComponent(password), callback); //$NON-NLS-1$ //$NON-NLS-2$
		} catch (RequestException e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("rawtypes")
	public static void performLogin(final AsyncCallback callback) {
		// let's only login if we are not actually logged in
		//SERVICE.isAuthenticated(new AsyncCallback<Boolean>() {

		CubicServiceCache.getService().isAuthenticated(new AsyncCallback<Boolean>() {
			public void onFailure(Throwable caught) {
				LoginDialog dialog = new LoginDialog(callback);
				dialog.center();
			}

			public void onSuccess(Boolean result) {
				if (!result) {
					LoginDialog dialog = new LoginDialog(callback);
					dialog.show();
				}
			}
		});
	}

	public void setCallback(AsyncCallback<Boolean> callback) {
		outerCallback = callback;
	}

	public boolean validate() {
		if (txtUsername.getText().length() < 2) {
			setNotify("Error, try again");
			return false;
		}
		return true;
	}

	public void setNotify(String text) {
		htmlNotify.addStyleName("cubic-dialog-login-error");
		htmlNotify.setText(text);
	}


}
